'''
Created on 20/05/2012

@author: Bruna, Bruno
'''
import math
import numpy
import csv

def calculate_rgb_normalized(red, green, blue):
    sum = float(red + green + blue)
    normalized_r = (red / sum)
    normalized_g = (green / sum)
    
    return numpy.matrix([[normalized_r, normalized_g]])

class Estimators:
    '''
        Reads a file that contains samples of colors and calculates mean and covariance (of Bivariate Gaussian) 
    '''
    def __init__(self, file_name):
        self.file_name = 'resources\\' + file_name
        self.mean = numpy.matrix([[0.0, 0.0]])
        self.covariance = numpy.matrix([[0.0, 0.0],[0.0, 0.0]])
        
        self.__extract_mean()
        self.__extract_covariance()

    def __create_CSVReader(self):
        file_handler = open(self.file_name)
        return csv.DictReader(file_handler)
    
    def __extract_mean(self):
        count = 0
    
        reader = self.__create_CSVReader()
        for row in reader:
            self.mean += calculate_rgb_normalized(int(row['Red']), int(row['Green']), int(row['Blue']))
            count += 1
            
        self.mean /= count
        
    def __extract_covariance(self):
        count = 0
    
        reader = self.__create_CSVReader()
        for row in reader:
            sample = calculate_rgb_normalized(int(row['Red']), int(row['Green']), int(row['Blue']))
            temp = sample - self.mean
            self.covariance += temp.T * temp
            count += 1
            
        self.covariance /= (count - 1)
        
class BivariateGaussian:
    def __init__(self, file_name):
        self.estimators = Estimators(file_name)
        self.inverse = self.estimators.covariance.I
        self.determinant = numpy.linalg.det(self.estimators.covariance)
        self.term1 = -2.0/2 * math.log(2 * math.pi)
        self.term2 = -1.0/2 * math.log(self.determinant)
        
    def p(self, red, green, blue):
        x = calculate_rgb_normalized(red, green, blue)
        term = x - self.estimators.mean
        term3 = -1.0/2 * term * self.inverse * term.T
        return self.term1 + self.term2 + term3
        
def print_arduino_defines(files, gaussians):
    for file in files:
        color = file[:-4]
        print "#define", color + "Ur", gaussians[file].estimators.mean[0,0]
        print "#define", color + "Ug", gaussians[file].estimators.mean[0,1]
        
        print "#define", color + "I11", gaussians[file].inverse[0,0]
        print "#define", color + "I12", gaussians[file].inverse[0,1]
        print "#define", color + "I22", gaussians[file].inverse[1,1]
    
        print "#define", color + "Det", gaussians[file].determinant
        print
    
        
if __name__ == "__main__":

    files = ["Blue.csv", "Red.csv", "Lilac.csv", "LightBlue.csv", "Green.csv", "Yellow.csv", "Orange.csv"]
    gaussians = dict()
    
    for file in files:
        gaussians[file] = BivariateGaussian(file)
        
    print_arduino_defines(files, gaussians)
    
    #while True:
        #red, green, blue = input("Red, Green, Blue: ")
        #for color in gaussians.keys():
            #print color[:-4], "->", gaussians[color].p(red, green, blue)
            
    